package com.weita.lightfood.service;


import com.weita.lightfood.model.dao.DishDao;
import com.weita.lightfood.model.dao.HistoryOrderDao;
import com.weita.lightfood.model.entity.Dish;
import com.weita.lightfood.model.entity.HealthReport;
import com.weita.lightfood.model.entity.HistoryOrder;
import com.weita.lightfood.model.query.dish.AddDishQuery;
import com.weita.lightfood.model.query.dish.UpdateTemplateQuery;
import com.weita.lightfood.model.vo.dish.DishTemplateDetailsVo;
import com.weita.lightfood.model.vo.dish.MaterialNameAndWeight;
import com.weita.lightfood.model.vo.dish.ShowIndexVo;
import com.weita.lightfood.model.vo.material.MateralNameNuvalueVo;
import com.weita.lightfood.utils.FileUploadUtil;
import com.weita.lightfood.utils.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author IT_Monster at 2019/03/28 14:18.
 */
@Service
public class DishService {
    static final private String URL_PATH = "D:\\01Programer\\IDEA\\workspace\\light-food\\src\\main\\resources\\static\\images\\dish\\";
    static final private String CLASS_PATH = "D:\\01Programer\\IDEA\\workspace\\light-food\\target\\classes\\static\\images\\dish\\";
    @Autowired
    private DishDao dishDao;
    @Autowired
    private MaterialService materialService;
    @Autowired
    private HistoryOrderDao historyOrderDao;
    @Autowired
    private LabelService labelService;
    @Autowired
    private HealthReportService healthReportService;

    /**
     * 向日期三餐发布表中根据日期进行数据操作，对应日期有数据则更新，无则插入
     * @param date
     * @param dishId
     * @param state
     */
    private void updateOrInsertHistoryOrder(String date, int dishId, int state) throws Exception {
        HistoryOrder historyOrder = historyOrderDao.getDishesIdByDate(date);
        if (historyOrder == null){
            //进行插入
            historyOrderDao.insertHistoryOrder(date,dishId,state);
        }else {
            //进行更新
            historyOrderDao.updateHistoryOrder(date,dishId,state);
        }
    }

    /**
     * 获取菜谱中精选食材名和功效介绍
     *
     * @param dishId
     * @return
     */
    public List<MateralNameNuvalueVo> getMaterialByMenuId(int dishId) throws Exception {
        return dishDao.getMaterialByMenuId(dishId);
    }


    /**
     * 获取一日之中三餐安排
     * @param date
     * @return
     */
    private Map<String, Dish> getDishesMap(String date) throws Exception {
        Map<String, Dish> oneDayDishes = new HashMap<>(3);

        //根据日期获取该日三餐菜品id
        HistoryOrder historyOrder = historyOrderDao.getDishesIdByDate(date);
        Dish breakfast = null;
        Dish lunch = null;
        Dish dinner = null;
        //根据菜品id获取菜品
        //获取早餐
        if (historyOrder.getBreakfastOrder() != null){
            breakfast = dishDao.getDishById(historyOrder.getBreakfastOrder());
        }

        //获取午餐
        if (historyOrder.getLunchOrder() != null){
            lunch = dishDao.getDishById(historyOrder.getLunchOrder());
        }

        //获取晚餐
        if (historyOrder.getDinnerOrder() != null){
            dinner = dishDao.getDishById(historyOrder.getDinnerOrder());
        }

        if (breakfast != null){
            oneDayDishes.put("breakfast",breakfast);
        }
        if (lunch != null){
            oneDayDishes.put("lunch",lunch);
        }
        if (dinner != null){
            oneDayDishes.put("dinner",dinner);
        }
        return oneDayDishes;
    }

    /**
     * 根据日期返回首页展示数据
     *
     * @param userId
     * @param date
     * @return
     */
    @Cacheable(cacheNames = "dish", key = "#date")
    public Map<String, ShowIndexVo> showIndex(int userId, String date) throws Exception {
        Map<String,ShowIndexVo> showIndexVos = new HashMap<>(3);
        ShowIndexVo breakfastVo = null;
        ShowIndexVo lunchVo = null;
        ShowIndexVo dinnerVo = null;
        //获取一日三餐
        Map<String , Dish> dishes = this.getDishesMap(date);

        //获取早餐
        Dish breakfast = dishes.get("breakfast");
        //获取午餐
        Dish lunch = dishes.get("lunch");
        //获取晚餐
        Dish dinner = dishes.get("dinner");
        if (breakfast != null){
            breakfastVo = this.convertor(breakfast);
            //为了将首页的热量转成用户预算热量
            breakfastVo.setCalorie(0);
        }

        if (lunch != null){
            lunchVo = this.convertor(lunch);
            //为了将首页的热量转成用户预算热量
            lunchVo.setCalorie(0);
        }

        if (dinner != null){
            dinnerVo = this.convertor(dinner);
            //为了将首页的热量转成用户预算热量
            dinnerVo.setCalorie(0);
        }

        if (breakfastVo != null){
            showIndexVos.put("0breakfast",breakfastVo);
        }
        if (lunchVo != null){
            showIndexVos.put("1lunch",lunchVo);
        }
        if (dinnerVo != null){
            showIndexVos.put("2dinner",dinnerVo);
        }

        //获取用户预算热量,为了将首页的热量转成用户预算热量
        HealthReport healthReport = healthReportService.getHealthReport(userId);
        double calorieBudget = healthReport.getCalorieBudget();
        Set<String> keys = showIndexVos.keySet();
        for (String key : keys) {
            showIndexVos.get(key).setCalorie((int) calorieBudget);
            break;
        }

        return showIndexVos;
    }

    /**
     * 将数据转换成首页展示数据
     *
     * @param dish
     * @return
     */
    private ShowIndexVo convertor(Dish dish) throws Exception {
        ShowIndexVo showIndexVo = new ShowIndexVo();
        showIndexVo.setDishId(dish.getId());
        showIndexVo.setCalorie(dish.getCalorie());
        showIndexVo.setDishName(dish.getName());
        showIndexVo.setState(dish.getState());
        showIndexVo.setPrice(dish.getPrice());
        //设置标签
        List<String> labels = dishDao.getLabelByDishId(dish.getId());
        String labelsString = StringUtils.join(labels.toArray(), ",");

        /*********获取主页展示食材**********/
        List<String> materials = dishDao.getHeadMaterialByDishId(dish.getId());
        String materialString = StringUtils.join(materials.toArray(), ",");

        showIndexVo.setLabels(labelsString);
        showIndexVo.setMaterials(materialString);
        //设置蛋白质含量
        showIndexVo.setProtein(dish.getProtein());
        //设置脂肪含量
        showIndexVo.setFat(dish.getFat());
        //设置碳水化合物含量
        showIndexVo.setCarbohydrate(dish.getCarbohydrate());
        showIndexVo.setPictureAddress(dish.getPictureAddress());
        return showIndexVo;
    }

    /**
     * 用户端菜品展示数据
     *
     * @param userId
     * @return
     */
    public Map<String,Map> showUserIndex(int userId) throws Exception {
        /******************************获取日期*************************************************/
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        c.add(Calendar.DATE, 0);
        //今日日期
        String today = sdf.format(c.getTime());
        c.add(Calendar.DATE, 1);
        //明天日期
        String tomorrow = sdf.format(c.getTime());
        c.add(Calendar.DATE, 2);
        //后天日期
        String afterTomorrow = sdf.format(c.getTime());
        /*****************************获取近三天菜谱**************************************************/
        Map<String, ShowIndexVo> todayDish = this.showIndex(userId, today);
        Map<String, ShowIndexVo> tomorrowDish = this.showIndex(userId, tomorrow);
        Map<String, ShowIndexVo> afterTomorrowDish = this.showIndex(userId, afterTomorrow);
        /****************************整合数据***************************************************/
        Map<String,Map> threeDaysDishes = new HashMap<>(3);
        threeDaysDishes.put("todayDish",todayDish);
        threeDaysDishes.put("tomorrowDish",tomorrowDish);
        threeDaysDishes.put("afterTomorrowDish",afterTomorrowDish);
        /*******************************************************************************/
        return threeDaysDishes;
    }

    /**
     * 获取所有模板
     * @return
     */
    public List<DishTemplateDetailsVo> getAllTemplate() throws Exception {
        List<Dish> dishes = dishDao.getAllTemplate();
        return this.dishToTemplate(dishes);
    }

    /**
     * 将菜品list集合转成模板list集合
     * @param dishes
     * @return
     */
    private List<DishTemplateDetailsVo> dishToTemplate (List<Dish> dishes) throws Exception {
        List<DishTemplateDetailsVo> dishTemplates = new ArrayList<>();

        for (Dish dish : dishes) {
            DishTemplateDetailsVo templateVo = new DishTemplateDetailsVo();
            templateVo.setCalorie(dish.getCalorie());
            templateVo.setId(dish.getId());
            templateVo.setName(dish.getName());
            templateVo.setPictureAddress(dish.getPictureAddress());
            templateVo.setState(dish.getState());
            templateVo.setPrice(dish.getPrice());
            //获取标签
            List<String> labels = dishDao.getLabelByDishId(dish.getId());
            String labelsString = StringUtil.stringListToString(labels);
            //获取展示食材
            List<String> headMaterialByDishId = dishDao.getHeadMaterialByDishId(dish.getId());
            String headMaterialString = StringUtil.stringListToString(headMaterialByDishId);
            templateVo.setLabels(labelsString);
            templateVo.setShowIndexMaterial(headMaterialString);

            templateVo.setCarbohydrate(dish.getCarbohydrate());
            templateVo.setFat(dish.getFat());
            templateVo.setProtein(dish.getProtein());


            List<MaterialNameAndWeight> material = dishDao.getMaterial(dish.getId());
            String materialName = "";
            String materialWeight = "";

            for (int i=0;i<material.size();i++){
                if (i<material.size()-1){
                    materialName = materialName + material.get(i).getName() + ",";
                    materialWeight = materialWeight + material.get(i).getWeight() + ",";
                }else {
                    materialName = materialName + material.get(i).getName();
                    materialWeight = materialWeight + material.get(i).getWeight();
                }
            }

            templateVo.setMaterial(materialName);
            templateVo.setMaterialWeight(materialWeight);

            List<String> choicenessMaterial = dishDao.getChoicenessMaterial(dish.getId());
            String choicenessMaterialString = StringUtil.stringListToString(choicenessMaterial);
            templateVo.setShowMaterial(choicenessMaterialString);
            dishTemplates.add(templateVo);
        }
        return dishTemplates;
    }


    /**
     * 发布菜品，保存到历史菜单,带上图片
     * @param addDishQuery
     * @param file
     * @return
     * @throws Exception
     */
    public String publishDishWithImg(AddDishQuery addDishQuery, MultipartFile file) throws Exception {
        //获取标签名列表
        //向菜单表中插入数据
        dishDao.addDish(addDishQuery);
        //向食材和标签中间表插入数据(必须向dish表中插入了数据，获取了addDishQuery的主键之后才能进行此操作)
        this.insertToLabAndMate(addDishQuery);

        int dishId = addDishQuery.getId();
        System.out.println("我在dishService的publishDishWithImg中，打印在向菜谱表插入数据后: "+ addDishQuery);
        //向历史菜单中添加数据
        this.updateOrInsertHistoryOrder(addDishQuery.getPublishDate(),dishId,addDishQuery.getState());

        try {
            //保存图片
            String fileName = dishId + ".jpg";
            FileUploadUtil.uploadImg(file,URL_PATH,fileName);
            FileUploadUtil.uploadImg(file,CLASS_PATH,fileName);
            //保存图片url
            String url = "images/dish/" + addDishQuery.getId() + ".jpg";
            dishDao.savePicPath(url,addDishQuery.getId());
        } catch (NullPointerException e) {
            System.out.println("上传的图片是空的");
        }
        return "发布成功";
    }

    /**
     * 删除菜品
     * @param dishId
     */
    public void deleteDish(int dishId) throws Exception {
        dishDao.deleteDish(dishId);
    }

    /**
     * 删除模板
     * @param dishId
     */
    public String deleteTemplate(int dishId) throws Exception {
        dishDao.deleteTemplate(dishId);
        return "删除模板成功";
    }

    /**
     * 通过模板名搜索模板
     * @param name
     * @return
     */
    public List<DishTemplateDetailsVo> searchTemplate(String name) throws Exception {
        List<Dish> dishes = dishDao.searchTemplate(name);
        return this.dishToTemplate(dishes);
    }


    /**
     * 向菜谱的食材、标签表中插入数据
     * @param addDishQuery
     */
    private void insertToLabAndMate(AddDishQuery addDishQuery) throws Exception {
        String[] labels = addDishQuery.getLabels().split(",");
        //获取食材名列表
        String[] material = addDishQuery.getMaterial().split(",");
        //获取食材重量列表
        String[] materialWeight = addDishQuery.getMaterialWeight().split(",");
        //获取精选食材名列表
        String[] showMaterial = addDishQuery.getShowMaterial().split(",");
        //获取首页展示食材名列表
        String[] showIndexMaterial = addDishQuery.getShowIndexMaterial().split(",");
        //菜谱id
        int dishId = addDishQuery.getId();
        //向菜单标签中间表中插入数据
        for (String s : labels) {
            int labelId = labelService.getLabelIdByName(s);
            if (labelId == -1){
                System.out.println("未根据标签名找到标签");
            }else {
                dishDao.dish__label(dishId, labelId);
            }
        }
        //向菜单食材中间表中插入数据
        for (int i = 0; i < material.length; i++) {
            //获取食材名
            String mname = material[i];
            //通过食材名获取食材id
            int id = materialService.getIdByMaterialName(mname);
            //获取食材重量
            String mwei = materialWeight[i];
            dishDao.dish__material(dishId, id, Integer.parseInt(mwei));
        }

        //设置首页展示食材
        for (String s : showIndexMaterial) {
            if (!"".equals(s)){
                int id = materialService.getIdByMaterialName(s);
                dishDao.setHeadFlag(id, 1);
            }
        }
        //设置精选食材
        for (String s : showMaterial) {
            //获取精选食材对应的食材id
            List<Integer> materialIds = materialService.getMaterialIdByChoicenessName(s);
            //将指定菜谱的指定食材设置为精选食材
            for (Integer materialId : materialIds) {
                dishDao.setChoiceness(materialId, 1,dishId);
            }
        }
    }

    /**
     * 修改模板
     * @param addDishQuery
     * @param img
     * @return
     * @throws Exception
     */
    public String updateTemplate(UpdateTemplateQuery addDishQuery, MultipartFile img) throws Exception {
        /*AddDishQuery addDishQuery = new AddDishQuery();*/

        //获取菜谱id
        int dishId = addDishQuery.getId();
        System.out.println("模板id"+dishId);
        //1.删除菜品标签，食材等相关信息
        dishDao.removeLabAndMate(dishId);
        //2.更新食材表
        dishDao.updateDish(addDishQuery);
        //3.重新插入新的标签，食材等信息
        this.insertToLabAndMate(addDishQuery);
        //4.修改图片
        if (img != null){
            String fileName = dishId + ".jpg";
            //保存图片
            FileUploadUtil.uploadImg(img,URL_PATH,fileName);
            FileUploadUtil.uploadImg(img,CLASS_PATH,fileName);
            //保存图片url
            String url = "images/dish/" + fileName;
            dishDao.savePicPath(url,dishId);
        }
        return "修改模板成功";
    }


    /**
     * 获取食谱所有食材名
     * @param dishId
     * @return
     */
    public List<String> getMaterialByDishId(int dishId) throws Exception {
        return dishDao.getMaterialByDishId(dishId);
    }


}
